package utils

import (
	"fmt"
	"gitee.com/jikey/elk-blog/setting"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"
)

var (
	long   = 0
	ti1    = int64(0)
	once   sync.Once
	client *oss.Client
	err    error
)

func Uploads(str []interface{}) []interface{} {
	for k, v := range str {
		str[k] = Upload(v.(string))
	}
	return str
}

// 使用sync.Once来保证oss.New函数只调用一次，避免重复创建OSSClient实例。
func getOssClient() *oss.Client {
	once.Do(func() {
		// 创建OSSClient实例。
		client, err = oss.New(setting.Config.Aliyun.Endpoint,
			setting.Config.Aliyun.AccessKey,
			setting.Config.Aliyun.SecretAccessKey)
		if err != nil {
			fmt.Println("Error:", err)
			os.Exit(-1)
		}
		fmt.Println("create ossClient")
	})
	fmt.Println("get ossClient")
	return client
}

func Upload(url string) string {
	// 创建OSSClient实例。
	client = getOssClient()
	t1 := time.Now().Unix()
	if ti1 != t1 { // 如果时间戳不一样,那么归零
		long = 0
	}
	ti1 = t1
	long++
	obj := fmt.Sprintf("article/%d%d.png", t1, long)
	// 获取存储空间。
	bucket, err := client.Bucket(setting.Config.Aliyun.BucketName)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	res, _ := http.Get(url)
	// 上传Byte数组。
	// err = bucket.PutObject(obj, bytes.NewReader(ReadImgData(url)))
	err = bucket.PutObject(obj, io.Reader(res.Body))
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	return setting.Config.Aliyun.InnerNet + obj
}

// ReadImgData 获取C的图片数据
func ReadImgData(url string) []byte {
	resp, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	pix, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	return pix
}

// RepImages 上传给定内容中非本站的图片，并替换为上传的图片链接 https://zhuanlan.zhihu.com/p/74047342
func RepImages(htmls string) string {
	var imgRE = regexp.MustCompile(`<img[^>]+\bsrc=["']([^"']+)["']`)
	imgs := imgRE.FindAllStringSubmatch(htmls, -1)
	out := make([]string, len(imgs))
	myImage := ""
	resHtml := htmls

	for i := range out {
		if !strings.HasPrefix(imgs[i][1], setting.Config.App.StaticDomain) {
			myImage = Upload(imgs[i][1])
			resHtml = strings.Replace(resHtml, imgs[i][1], myImage, -1)
			out[i] = imgs[i][1]
		}
	}

	return resHtml
}

func OssUpload(key string, file io.Reader) (string, error) {
	client = getOssClient()
	// 获取存储空间。
	bucket, err := client.Bucket(setting.Config.Aliyun.BucketName)
	if err != nil {
		return "", err
	}
	// 上传文件。
	err = bucket.PutObject(key, file)
	if err != nil {
		return "", err
	}
	// https://jxcatimg.oss-cn-shenzhen.aliyuncs.com/articles/202107/1626401559-1564453109_219427.jpg
	return setting.Config.Aliyun.InnerNet + key, nil
}

func OSSUploadFile(c *gin.Context) (bool, string) {
	fileHeader, err := c.FormFile("file")
	if err != nil {
		return false, "参数有误"
	}
	fileExt := filepath.Ext(fileHeader.Filename)
	allowExts := []string{".jpg", ".png", ".gif", ".jpeg", ".doc", ".docx", ".ppt", ".pptx", ".xls", ".xlsx", ".pdf"}
	allowFlag := false
	for _, ext := range allowExts {
		if ext == fileExt {
			allowFlag = true
			break
		}
	}
	if !allowFlag {
		return false, "不允许的类型"
	}

	now := time.Now()
	// 文件存放路径
	fileDir := fmt.Sprintf("articles/%s", now.Format("200601"))

	// 文件名称
	timeStamp := now.Unix()
	fileName := fmt.Sprintf("%d-%s", timeStamp, fileHeader.Filename)
	// 文件key
	fileKey := filepath.Join(fileDir, fileName)

	src, err := fileHeader.Open()
	if err != nil {
		return false, "上传失败"
	}
	defer src.Close()

	res, err := OssUpload(fileKey, src)
	if err != nil {
		return false, "上传失败"
	}
	return true, res
}
